home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 22
/
Aminet 22 (1997)(GTI - Schatztruhe)[!][Dec 1997].iso
/
Aminet
/
util
/
blank
/
BeyondTheDark.lha
/
BeyondTheDark
/
Developer
/
Source
/
Skeleton
/
Skeleton.c
< prev
Wrap
C/C++ Source or Header
|
1997-10-14
|
12KB
|
428 lines
/*
Skeleton Library for BTD
Comments by Markus Illenseer
This source tries to give valuable hints to write a Modul
for BTD. As you will see, this is quite easy, even if it is
the first time you write a library.
This Skeleton Blanker draws random dots in 4 colors for a certain time,
then cleans up the screen and starts again. Nothing sophisticated.
Also do refer to BTD.h for global defines and structures.
*/
#include <exec/memory.h>
#include <exec/execbase.h>
#include <graphics/gfxbase.h>
#include <intuition/intuitionbase.h>
#include <libraries/iffparse.h>
#include <utility/tagitem.h>
#include <clib/macros.h>
#define __USE_SYSBASE 42
#include <proto/exec.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
#include <proto/utility.h>
#include <BTD.h>
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct Library *UtilityBase;
/*
Don't open any libraries by yourself. This _must_ be done
in the assembler part of the library.
Be sure your library is re-entrant. Means, one must be able to
open the library several times at once. So don't use global
variables other than static (unchangable) ones. Use ModulStruct
for that purpose.
*/
/* #define DEBUG YES */
/*
Remove above comment braces (uncomment) to use the Debug-Output.
Use Terminal connected to serial line, or use sushi to
redirect the output. Be carefull with modems!
Remember to add the Debug.lib in the Makefile.
DEBUG_PRINT prints only text.
DEBUG_PRINTF prints any text and one (!) variable of any kind
This is the only easy way to debug libaries! The SDB or other
debuggers have some problems with libraires, at least as source
level debuggers.
*/
#ifdef DEBUG
void KPrintF(char *,...);
#define DEBUG_PRINTF(a,b) KPrintF(a,b);
#define DEBUG_PRINT(a) KPrintF(a)
#else
#define DEBUG_PRINTF(a,b)
#define DEBUG_PRINT(a)
#endif
/* Now we define the Macros for easy access to the Tag-Entries */
#define DTAG(o) (BTD_Client+(o))
#define ST_Seconds DTAG(0)
/* How much time we give, until the screen is cleaned up again */
#define DEF_SECONDS 5L
#define MAX_SECONDS 60L
/*
This structure defines the INTEGER parameters, which the user
can supply. Skeleton requires only the seconds until it will
clean up the screen. For other type of paramters, refer to BTD.h
*/
struct BTDInteger SkeletonIntParams[] =
{
ST_Seconds,"Seconds",BTDPT_INTEGER,DEF_SECONDS,1L,MAX_SECONDS,TRUE,
};
/*
This Taglist is send to the Preference-Programm which will
open a window with the hereby supplied gadgets. Skeleton needs
only the one Integer-Slider
*/
struct BTDNode *SkeletonParams[] =
{
&SkeletonIntParams[0].BI_Node,
NULL
};
/*
This structure sends some info about the modul to the Preference-
Programm. MAKE_ID is required for MUI, and will make it possible
to save the position of this specific preference window.
First string defines the NAME of the blanker, possibly something
different than the probaly cryptic filename of the library.
Second string contains a short description about the blanker. A \n will
split up the string into a new line.
Third string should contain your Name and a Copyright message if
necessary.
The Version Number is not defined here, but in the Assembler-Part
of the source!
Last Tag is the Node-Info, which will request the user for parameters
with above given List in BTDNode.
*/
struct BTDInfo SkeletonInfo =
{
BTDI_Revision,MAKE_ID('S','K','E','L'),
"Skeleton Blanker","Skeleton is intended for programmers\n among you peoples!\nJust a simple and boring blanker modul","Markus Illenseer 1994",
SkeletonParams
};
/*
This is our 'global' structure for the skeleton blanker. I refer to
it as ModulStruct.
Remember that this is the only way to hold global data for each
invoked modul out of this library. The Skeleton Blanker will only
hold info about the supplied second-parameter and about the time when
the screen was cleaned up the last time. And of course it will hold
the BTDDrawInfo, which contains lot of required info, eg. RastPort.
If you require anything sophisticated like ImageData, have a look into
the other supplied modules.
*/
struct SkeletonStruct
{
struct BTDDrawInfo *BTDDrawInfo;
LONG Seconds;
LONG Time;
LONG RandN,RandF,RandI;
};
/* library stuff */
char MyBlankerName[] = "skeleton.btd";
char MyBlankerID[] = "Skeleton Blanker V" VERSION "." REVISION " for BTD";
LONG MyBlankerLibInit(void)
{
if (GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",37L))
{
if (IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",37L))
{
if (UtilityBase=OpenLibrary("utility.library",37L)) return TRUE;
CloseLibrary (&IntuitionBase->LibNode);
}
CloseLibrary (&GfxBase->LibNode);
}
return FALSE;
}
void MyBlankerLibFree(void)
{
CloseLibrary (UtilityBase);
CloseLibrary (&IntuitionBase->LibNode);
CloseLibrary (&GfxBase->LibNode);
}
/* implementation of library functions */
struct BTDInfo *QueryMyBlanker(void)
{
return &SkeletonInfo;
}
/*
The next two functions are some sophisticated Randomnizers
which are based upon (mathematic) statistic defined true
Randomnizers. All they need is a seed, afterwards they will use
the current time as a base for future randoms.
Normally we would have some global variabled for RandN, RandF and
RandI, but as we need to be re-entrant, we need to store this info
in the ModulStruct above.
*/
void __regargs InitRandom(struct SkeletonStruct *Skel,ULONG Instance)
{
ULONG Time[2];
CurrentTime (&Time[0],&Time[1]);
Skel->RandN=(LONG)Time[0];
if (Time[1]<1024L) Time[1]|=1;
else Time[1]>>=10;
Time[1]^=Instance;
Skel->RandF=4*Time[1]+1;
Skel->RandI=2*Time[1]+1;
}
WORD __regargs Random(struct SkeletonStruct *Skel,WORD Max)
{
Skel->RandN=Skel->RandF*Skel->RandN+Skel->RandI;
if (Skel->RandN<0L) Skel->RandN=-Skel->RandN;
return (WORD)(Skel->RandN%Max);
}
/*
This is the first procedure every modul requires. It will initialize
the modul, eat required memory, set colors, whatever. This function
should be as short as possible. No heavy calculations belong here
struct ModulStruct InitModul(struct TagItem *TagList)
Input: TagList is supplied from BTD-CX, the server, and will send
you all the parameters you requested from the user in above
structure BTDInfo.
Output: Fully initialized ModulStruct for further use, is returned
to the server, who will then invoke AnimModul() with this
structure.
*/
struct SkeletonStruct *InitMyBlanker(struct TagItem *TagList)
{
struct SkeletonStruct *SkelStruct;
struct BTDDrawInfo *BTDDrawInfo;
ULONG *Error,Dummy,Instance,Index;
DEBUG_PRINT("Skeleton: Initialize Modul\n");
/* Find the Entry for the BTDDrawInfo (see BTD.h) and make local copy */
if ((BTDDrawInfo=(struct BTDDrawInfo *)
GetTagData(BTD_DrawInfo,NULL,TagList))==NULL) return NULL;
/*
Get us the Dummy, which will contain Error-Messages if we fail to
initialize our Modul. The server then knows we failed and will display
a black part on the screen
*/
Error=(LONG *)GetTagData(BTD_Error,(ULONG)&Dummy,TagList);
/*
Allocate the required MEM for the SkeletonStruct, on error report
a Memory-error to the server and return home
*/
if ((SkelStruct=AllocVec(sizeof(struct SkeletonStruct),MEMF_PUBLIC|MEMF_CLEAR))==NULL)
{
*Error=BTDERR_Memory;
return NULL;
}
/*
copy local BTDDrawInfo into global structure for future use in
AnimModul()
*/
SkelStruct->BTDDrawInfo=BTDDrawInfo;
/*
The Instance is sort of OpenCounter and is often used to initialize
a Randomnizer, so that same modules won't use same random-seed
*/
Instance=GetTagData(BTD_Instance,0L,TagList);
InitRandom(SkelStruct,Instance);
/* Get us the user-supplied parameter SECONDS */
SkelStruct->Seconds=GetTagData(ST_Seconds,DEF_SECONDS,TagList);
/*
Set an initial value, not really required to do so, as we allocated
the SkelStruct with MEMF_CLEAR flag
*/
SkelStruct->Time=0L;
/*
Now set our requested colors to any RGB-Tripel, you MUST use
this array, otherwise you won't get your colors, but anything
else. Can yield to a Guru if you do that!
*/
for(Index=0; Index<4; Index++)
{
BTDDrawInfo->BDI_Red[BTDDrawInfo->BDI_Pens[Index]]=Random(SkelStruct,255);
BTDDrawInfo->BDI_Green[BTDDrawInfo->BDI_Pens[Index]]=Random(SkelStruct,255);
BTDDrawInfo->BDI_Blue[BTDDrawInfo->BDI_Pens[Index]]=Random(SkelStruct,255);
BTDDrawInfo->BDI_Changed[BTDDrawInfo->BDI_Pens[Index]]=TRUE;
}
/* Everything's done. Return the structure for future use */
return SkelStruct;
}
/* This is the second procedure required for every modul. It should
do anything required to free resources, free mem and so on.
void EndMyBlanker(struct ModulStruct *ModulStruct)
Input: ModulStruct supplied from server BTD-CX
Output: None. Should all be freed up */
void EndMyBlanker(struct SkeletonStruct *SkelStruct)
{
DEBUG_PRINT("Skeleton: about to finish Modul\n");
FreeVec (SkelStruct);
}
/* Third procedure required for a modul. This one is called by the
server every once in a second. You are not allowed to do anything
which would yield into a FOREVER-Loop or do anything like a busy-loop
or something unstoppable.
If you need to do a loop from TOP to BOTTOM (TOP+HEIGHT), add a counter
in ModulStruct: ypos. Best would even to add xpos also, if required.
These restictions are all due to the fact, that the user want's his
screen back as fast as possible!
void AnimMyBlanker(struct ModulStruct *ModulStruct)
Input: ModulStruct supplied from server BTD-CX.
OutPut: None.
*/
void AnimMyBlanker(struct SkeletonStruct *SkelStruct)
{
ULONG Seconds,Micros;
/* Hum, below DEBUG_PRINT not that usefull. Remove it, or replace
it with anything you need to check */
DEBUG_PRINT("Skeleton: Animate\n");
/* Get us the current time. */
CurrentTime (&Seconds,&Micros);
if (Seconds>=SkelStruct->Time)
{
/* Wait for that the pointer is at the top of the screen */
WaitTOF();
/* Calculate next timeslide */
SkelStruct->Time=Seconds+SkelStruct->Seconds;
/* Set Background color, attention, have a look at the color! */
SetAPen(SkelStruct->BTDDrawInfo->BDI_RPort,BTD_BgPen);
/* Fill our part of the screen with background color */
RectFill (SkelStruct->BTDDrawInfo->BDI_RPort,
SkelStruct->BTDDrawInfo->BDI_Left,
SkelStruct->BTDDrawInfo->BDI_Top,
SkelStruct->BTDDrawInfo->BDI_Left+SkelStruct->BTDDrawInfo->BDI_Width-1,
SkelStruct->BTDDrawInfo->BDI_Top+SkelStruct->BTDDrawInfo->BDI_Height-1);
}
/* Now let's do the magic Animation of Skeleton */
/* Choose Random Color and set Pen accordingly */
SetAPen (SkelStruct->BTDDrawInfo->BDI_RPort,
SkelStruct->BTDDrawInfo->BDI_Pens[Random(SkelStruct,4)]);
/*
You can speed up the process, if you store LEFT, TOP, HEIGHT. WIDTH
in ModulStruct directly, rather than in a pointer to BTDDrawInfo
*/
WritePixel (SkelStruct->BTDDrawInfo->BDI_RPort,
SkelStruct->BTDDrawInfo->BDI_Left+Random(SkelStruct,SkelStruct->BTDDrawInfo->BDI_Width),
SkelStruct->BTDDrawInfo->BDI_Top+Random(SkelStruct,SkelStruct->BTDDrawInfo->BDI_Height));
}
ULONG PenCountMyBlanker(struct TagItem *TagList)
{
/*
We request to use 4 colors, we _will_ get them!
We would even get 324 colors, if there is a screenmode with that
many colors, and the servers gives us that many.
If the servers sees that we need more colors as he can provide with
his used screenmode, he won't use our modul
*/
return 4L;
}